#include <ctime>
#include <unistd.h>
#include "block_queue.hpp"
#include "task.hpp"

const int num = 5;

typedef block_queue<task> block_queue_t;
const std::string ops = "+-*/%";

void* producer(void* args)
{
    block_queue_t* bq = static_cast<block_queue_t*>(args);

    while (true)
    {
        int x = rand() % 10;
        int y = rand() % 10;
        int op = ops[rand() % ops.size()];
        task t(x, y, op);
        bq->push(t);
        std::cout << "producer produce a data: " << t.pformat() << std::endl;

        sleep(1);
    }
    return nullptr;
}

void* consumer(void* args)
{
    block_queue_t* bq = static_cast<block_queue_t*>(args);

    while (true)
    {
        task t;
        bq->pop(&t);
        t();
        std::cout << "consumer consume a data: " << t.cformat() << std::endl;
    }
    return nullptr;
}

/*
typedef block_queue<int> block_queue_t;

void* producer(void* args)
{
    block_queue_t* bq = static_cast<block_queue_t*>(args);

    while (true)
    {
        int data = rand() % 10;
        bq->push(data);
        std::cout << "producer produce a data: " << data << std::endl;

        sleep(1);
    }
    return nullptr;
}

void* consumer(void* args)
{
    block_queue_t* bq = static_cast<block_queue_t*>(args);

    while (true)
    {
        int data = 0;
        bq->pop(&data);
        std::cout << "consumer consume a data: " << data << std::endl;
    }
    return nullptr;
}
*/

int main()
{
    srand((unsigned int)time(nullptr));
    block_queue_t* bq = new block_queue_t;

    pthread_t p[num], c[num];

    for (int i = 0; i < num; i++)
    {
        pthread_create(p+i, nullptr, producer, bq);
        pthread_create(c+i, nullptr, consumer, bq);
    }

    for (int i = 0; i < num; i++)
    {
        pthread_join(p[i], nullptr);
        pthread_join(c[i], nullptr);
    }

    delete bq;
    return 0;
}
